﻿using System;
using System.Configuration;
using System.IO;
using EPiServer;
using EPiServer.BaseLibrary;
using EPiServer.Configuration;
using EPiServer.Core;
using EPiServer.DataAccess;
using EPiServer.Framework.Initialization;
using EPiServer.Implementation;
using EPiServer.Tests.Environment;
using EPiServer.Web;
using EPiServer.Web.Hosting;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using InitializationModule = EPiServer.Framework.Initialization.InitializationModule;

namespace TemplateFoundation.Tests.Environment
{
    public static class EPiServerInitializer
    {
        /// <summary>
        /// Cleans up after tests by removing copied assemblies etc
        /// </summary>
        public static void Cleanup()
        {
            
        }

        /// <summary>
        /// Initializes EPiServer
        /// </summary>
        /// <param name="context">The test context for which EPiServer is initialized</param>
        public static void Initialize(TestContext context)
        {
            // Configure Global settings
            try
            {
                Global.BaseDirectory = context.TestDeploymentDir;
                Global.InstanceName = "EPiServer Unit Test";
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to configure Global class", ex);
            }

            // Copy embedded language file to test deployment directory
            try
            {
                // Create lang folder
                var langFolder = Directory.CreateDirectory(Global.BaseDirectory).CreateSubdirectory("lang");

                // Create a language file based on the embedded resource
                using (var langFile = File.CreateText(langFolder.FullName + "\\translations.xml"))
                {
                    langFile.Write(EmbeddedResourceLoader.LoadTextFile("EmbeddedResources.translations.xml"));

                    langFile.Close();
                }
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to copy language file to test deployment directory", ex);
            }

            // Initialize settings from App.config
            try
            {
                Settings.InitializeAllSettings(ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None));
            }
            catch (ConfigurationErrorsException ex)
            {
                throw new EPiServerTestException("The application configuration file does not seem to contain required EPiServer configuration", ex);
            }
            
            // Map host settings
            try
            {
                SiteMappingConfiguration.Instance=new SiteMappingConfiguration();
                Settings.Instance = Settings.MapHostToSettings("*", true);
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to map host settings", ex);
            }

            // Initialize ClassFactory
            try
            {
                ClassFactory.Instance = new DefaultBaseLibraryFactory(String.Empty);
                ClassFactory.RegisterClass(typeof(IRuntimeCache), typeof(DefaultRuntimeCache));
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to initialize ClassFactory", ex);
            }

            // Initialize hosting environment
            try
            {
                // Use a custom hosting environment designed to run without a web context
                GenericHostingEnvironment.Instance = new EPiServerHostingEnvironment();
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Could not initialize VPP", ex);
            }

            // Configure data access
            try
            {
                DataAccessBase.Initialize(
                    ConfigurationManager.ConnectionStrings[Settings.Instance.ConnectionStringName],
                    TimeSpan.Zero,
                    0,
                    TimeSpan.Zero);
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to set up database access", ex);
            }

            // Start EPiServer initialization
            try
            {
                InitializationModule.FrameworkInitialization(HostType.Service);
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("EPiServer framework could not be initialized, perhaps EPiServer or third-party assemblies are missing?", ex);
            }

            // Set up basic website content
            try
            {
                if (Resources.InitializeWebsiteContentOnStartup.Equals("true", StringComparison.OrdinalIgnoreCase))
                {
                    PageStructure.SetupWebsiteContent();
                }
            }
            catch (Exception ex)
            {
                throw new EPiServerTestException("Unable to set up basic web content", ex);
            }
        }
    }
}
